﻿using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LunarSF.SHomeWorkshop.LunarMind
{
    class CustomFoldingStrategy : AbstractFoldingStrategy
    {
        /// <summary>
        /// Gets/Sets the opening brace. The default value is '试题＞＞'.
        /// </summary>
        public string OpenBrace { get; set; }

        /// <summary>
        /// Gets/Sets the closing brace. The value is '〓〓〓〓〓〓'.
        /// </summary>
        public string CloseBrace { get; set; }

        private ICSharpCode.AvalonEdit.TextEditor edit;

        public ICSharpCode.AvalonEdit.TextEditor Edit { get { return this.edit; } }

        /// <summary>
        /// Creates a new BraceFoldingStrategy.
        /// </summary>
        public CustomFoldingStrategy(ICSharpCode.AvalonEdit.TextEditor edit)
        {
            this.edit = edit;
            this.OpenBrace = "试题＞＞";
            this.CloseBrace = "〓〓〓〓〓〓";
        }

        /// <summary>
        /// Create <see cref="NewFolding"/>s for the specified document.
        /// </summary>
        public override IEnumerable<NewFolding> CreateNewFoldings(TextDocument document, out int firstErrorOffset)
        {
            firstErrorOffset = -1;
            return CreateNewFoldings(document);
        }

        /// <summary>
        /// Create <see cref="NewFolding"/>s for the specified document.
        /// </summary>
        public IEnumerable<NewFolding> CreateNewFoldings(ITextSource document)
        {
            List<NewFolding> newFoldings = new List<NewFolding>();

            Stack<int> startOffsets = new Stack<int>();
            string openingBrace = this.OpenBrace;
            string closingBrace = this.CloseBrace;

            for (int i = 1; i <= edit.LineCount; i++)
            {
                var line = edit.Document.GetLineByNumber(i);
                var preLine = line.PreviousLine;

                string text = edit.Document.GetText(line.Offset, line.Length).TrimStart();

                if (text.StartsWith(openingBrace))
                {
                    if (preLine != null && startOffsets.Count > 0)
                    {
                        int startOffset = startOffsets.Pop();
                        // don't fold if opening and closing brace are on the same line
                        if (startOffset < preLine.Offset)
                        {
                            newFoldings.Add(new NewFolding(startOffset, preLine.EndOffset)
                            {
                                Name = openingBrace,
                            });
                        }
                    }

                    startOffsets.Push(line.Offset);
                }
                else if (text.StartsWith(closingBrace) && startOffsets.Count > 0)
                {
                    int startOffset = startOffsets.Pop();
                    // don't fold if opening and closing brace are on the same line
                    if (startOffset < line.EndOffset)
                    {
                        newFoldings.Add(new NewFolding(startOffset, line.EndOffset)
                        {
                            Name = openingBrace,
                        });
                    }
                }
            }
            newFoldings.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset));
            return newFoldings;
        }
    }
}
